package com.xiyuan.smartutils.template.engine;

import com.xiyuan.smartutils.StrUtils;
import com.xiyuan.smartutils.template.engine.statement.Statement;

import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * 已经编译的页面结构对象
 *
 * @author lgz 2020年12月15日 新建与整理
 */
public class Template implements Serializable {
    private static final long serialVersionUID = 1L;
    // 文件最后修改时间
    private long lastModified;
    
    // 页面路径
    private String path;
    // 页面表达式
    private final LinkedList<Statement> stmts = new LinkedList<Statement>();
    private Throwable error;
    private String id;
    
    public String getId() {
        return id;
    }
    
    public Template setId(String id) {
        this.id = id;
        return this;
    }
    
    /**
     * 获取页面编译异常
     */
    public Throwable getError() {
        return error;
    }
    
    public void setError(Throwable error) {
        this.error = error;
    }
    
    Template(String filePath) {
        this.path = filePath;
        this.lastModified = System.nanoTime();
    }
    
    public long getLastModified() {
        return lastModified;
    }
    
    public Template setLastModified(long lastmodified) {
        this.lastModified = lastmodified;
        return this;
    }
    
    public String getPath() {
        return path;
    }
    
    public void setPath(String path) {
        this.path = path;
    }
    
    void addStatement(Statement stmt) {
        if (stmt != null) {stmts.add(stmt);}
    }
    
    /**
     * 执行页面渲染，生成html
     */
    public void execute(VariableMap variableMap, PrintWriter out) {
        try {
            for (Statement stmt : stmts) {stmt.execute(variableMap, out);}
        }
        catch (Exception e) {
            if (e instanceof RuntimeException) {
                throw (RuntimeException) e;
            }
            
            throw new RuntimeException(StrUtils.trimToEmpty(e.getMessage()), e);
        }
    }
    
    /**
     * 运行模板 <br>
     * 取值顺序 代码块局部变量 > 模板文档（var）变量 > paramMap > scopes > innerObjs
     *
     * @param paramMap  参数表
     * @param scopes    作用于参数表
     * @param innerObjs 内置对象
     * @return
     */
    public String execute(Map<String, Object> paramMap, List<ParamScope> scopes, Map<String, Object> innerObjs) {
        
        VariableMap variableMap = new VariableMap(paramMap, scopes, innerObjs);
        StringWriter stringWriter = new StringWriter();
        execute(variableMap, new PrintWriter(stringWriter));
        return stringWriter.toString();
    }
    
    /**
     * 运行模板 <br>
     * 取值顺序 代码块局部变量 > 模板文档（var）变量 > paramMap > scopes
     *
     * @param paramMap  参数表
     * @param scopes    作用于参数表
     * @return
     */
    public String execute(Map<String, Object> paramMap, List<ParamScope> scopes){
        return execute(paramMap, scopes, null);
    }
    
    /**
     * 运行模板 <br>
     * 取值顺序 代码块局部变量 > 模板文档（var）变量 > paramMap > scopes
     *
     * @param paramMap  参数表
     * @return
     */
    public String execute(Map<String, Object> paramMap){
        return execute(paramMap, null, null);
    }
    
    public String execute(){
        return execute(null, null, null);
    }
    
    /**************************************************/
    /******  静态调用 *******************************/
    /**************************************************/
    
    public static Template parseFile(String filePath) {
        return TemplateResolver.resolveFile(filePath);
    }
}
